/* Copyright (c) 2021-2024 Qualcomm Technologies International, Ltd. */
/* %%version */

#include "mcp_private.h"
#include "mcp_debug.h"
#include "mcp_init.h"
#include "mcp_destroy.h"
#include "mcp_indication.h"
#include "mcp_read.h"
#include "mcp_write.h"
#include "mcp_notification.h"
#include "mcp_common.h"
#include "gatt_service_discovery_lib.h"
#ifndef EXCLUDE_GATT_OTS_CLIENT_MODULE
#include "mcp_optional_service_init.h"
#include "mcp_ots_operation_handler.h"
#endif /* EXCLUDE_GATT_OTS_CLIENT_MODULE */

CsrBool mcpInstFindBySrvcHndl(CsrCmnListElm_t *elem, void *data)
{
    ProfileHandleListElm_t *profile_hndl_elm = (ProfileHandleListElm_t *)elem;
    ServiceHandle profile_handle = *(ServiceHandle *)data;

    if (profile_hndl_elm)
        return (profile_hndl_elm->profile_handle == profile_handle);

    return FALSE;
}

CsrBool mcpProfileHndlFindByBtConnId(CsrCmnListElm_t *elem, void *data)
{
    ProfileHandleListElm_t *profile_hndl_elm = (ProfileHandleListElm_t *)elem;
    CsrBtConnId     btConnId   = *(CsrBtConnId *) data;
    MCP *mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(profile_hndl_elm->profile_handle);

    if (mcpInst)
        return (mcpInst->cid == btConnId);

    return FALSE;
}

CsrBool mcpProfileHndlFindByMcsSrvcHndl(CsrCmnListElm_t *elem, void *data)
{
    ProfileHandleListElm_t *profile_hndl_elm = (ProfileHandleListElm_t *)elem;
    ServiceHandle mcs_srvc_hndl = *(ServiceHandle *)data;
    MCP *mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(profile_hndl_elm->profile_handle);

    if (mcpInst)
        return (mcpInst->mcsSrvcHndl == mcs_srvc_hndl);

    return FALSE;
}

#ifndef EXCLUDE_GATT_OTS_CLIENT_MODULE
CsrBool mcpProfileHndlFindByOtsSrvcHndl(CsrCmnListElm_t *elem, void *data)
{
    ProfileHandleListElm_t *profile_hndl_elm = (ProfileHandleListElm_t *)elem;
    ServiceHandle ots_srvc_hndl = *(ServiceHandle *)data;
    MCP *mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(profile_hndl_elm->profile_handle);

    if (mcpInst)
        return (mcpInst->otsSrvcHndl == ots_srvc_hndl);

    return FALSE;
}
#endif /* EXCLUDE_GATT_OTS_CLIENT_MODULE */


/****************************************************************************/
static void handleGattSrvcDiscMsg(McpMainInst *inst, Msg *msg)
{
    MCP *mcpInst = NULL;
    ProfileHandleListElm_t* elem = NULL;
    GattSdPrim* prim = (GattSdPrim*)msg;

    switch (*prim)
    {
        case GATT_SERVICE_DISCOVERY_FIND_SERVICE_RANGE_CFM:
        {
            GATT_SERVICE_DISCOVERY_FIND_SERVICE_RANGE_CFM_T *cfm =
                (GATT_SERVICE_DISCOVERY_FIND_SERVICE_RANGE_CFM_T *) msg;

            elem = MCP_FIND_PROFILE_HANDLE_BY_BTCONNID(inst->profileHandleList, cfm->cid);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst == NULL)
                return;

            if ((cfm->result == GATT_SD_RESULT_SUCCESS) && cfm->srvcInfoCount)
            {
                uint16 index, count;

                count = cfm->srvcInfoCount;
                mcpInst->mcsCounter = cfm->srvcInfoCount;
                mcpInst->mcsNum = cfm->srvcInfoCount;

                for (index = 0; index < count; index++)
                {
                    GattMcsClientInitData init_data;
                    MCP_DEBUG("(MCP) : Start Hndl = 0x%x, End Hndl = 0x%x, Id = 0x%x\n",
                               cfm->srvcInfo[0].startHandle, cfm->srvcInfo[0].endHandle, cfm->srvcInfo[0].srvcId);

                    init_data.cid = cfm->cid;
                    init_data.startHandle = cfm->srvcInfo[index].startHandle;
                    init_data.endHandle = cfm->srvcInfo[index].endHandle;

                    GattMcsClientInitReq(mcpInst->libTask, &init_data, NULL);
                }
                free(cfm->srvcInfo);
            }
            else
            {
                mcpSendInitCfm(mcpInst, MCP_STATUS_DISCOVERY_ERR);
                MCP_REMOVE_SERVICE_HANDLE(inst->profileHandleList, mcpInst->mcpSrvcHndl);
                FREE_MCP_CLIENT_INST(mcpInst->mcpSrvcHndl);
            }
            break;
        }

#ifndef EXCLUDE_GATT_OTS_CLIENT_MODULE
        case  GATT_SERVICE_DISCOVERY_FIND_INCL_SRVC_RANGE_CFM:
        {
            GATT_SERVICE_DISCOVERY_FIND_INCL_SRVC_RANGE_CFM_T *cfm =
                   (GATT_SERVICE_DISCOVERY_FIND_INCL_SRVC_RANGE_CFM_T*)msg;

           elem = MCP_FIND_PROFILE_HANDLE_BY_BTCONNID(inst->profileHandleList, cfm->cid);

           if (elem)
           {
               mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
           }

           if (mcpInst && cfm->result == GATT_SD_RESULT_SUCCESS)
           {
                /* Perform GATT OTS init */
                uint16 index;
                mcpInst->otsCounter = cfm->srvcInfoCount;
                mcpInst->otsNum = cfm->srvcInfoCount;

                for (index = 0; index < cfm->srvcInfoCount; index++)
                {
                    GattOtscInitData init_data;
                    MCP_DEBUG("(MCP-OTS) : Start Hndl = 0x%x, End Hndl = 0x%x, Id = 0x%x\n",
                               cfm->srvcInfo[0].startHandle, cfm->srvcInfo[0].endHandle, cfm->srvcInfo[0].srvcId);

                    init_data.cid = cfm->cid;
                    init_data.startHandle = cfm->srvcInfo[index].startHandle;
                    init_data.endHandle = cfm->srvcInfo[index].endHandle;

                    GattOtscInitReq(mcpInst->libTask, &init_data, NULL);
                }
                free(cfm->srvcInfo);
           }

           break;
        }

        case GATT_SERVICE_DISCOVERY_INCL_SRVC_START_CFM:
        {
            GATT_SERVICE_DISCOVERY_INCL_SRVC_START_CFM_T *cfm =
                   (GATT_SERVICE_DISCOVERY_INCL_SRVC_START_CFM_T*)msg;

            elem = MCP_FIND_PROFILE_HANDLE_BY_BTCONNID(inst->profileHandleList, cfm->cid);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                if (cfm->result == GATT_SD_RESULT_SUCCESS)
                {
                    GattServiceDiscoverFindIncludedServiceRange(mcpInst->libTask,
                            cfm->cid,
                            GATT_SD_GMCS_SRVC,
                            GATT_SD_OTS_SRVC);
                }
                else if (cfm->result != GATT_SD_RESULT_INPROGRESS)
                {
                    mcpSendOptServInitCfm(mcpInst, MCP_OPTIONAL_SERVICE_INVALID, MCP_STATUS_DISCOVERY_ERR, MCP_OTS_INVALID_HANDLE);
                }
            }
            break;
        }
#endif /* EXCLUDE_GATT_OTS_CLIENT_MODULE */

        default:
        {
            /* Unrecognised GATT Manager message */
        }
        break;
    }
}

/*************************************************************/
static void mcpHandleGattMcsClientMsg(McpMainInst *inst, void *msg)
{
    MCP * mcpInst = NULL;
    ProfileHandleListElm_t* elem = NULL;
    GattMcsClientMessageId *prim = (GattMcsClientMessageId *)msg;

    MCP_INFO("mcpHandleGattMcsClientMsg MESSAGE:GattMcsClientMessageId:0x%x", *prim);

    switch (*prim)
    {
        case GATT_MCS_CLIENT_INIT_CFM:
        {
            const GattMcsClientInitCfm* message;
            message = (GattMcsClientInitCfm*) msg;
            /* Find mcp instance using connection_id_t */
            elem = MCP_FIND_PROFILE_HANDLE_BY_BTCONNID(inst->profileHandleList,
                                                       message->cid);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
                mcpHandleMcsClientInitResp(mcpInst,
                                           (const GattMcsClientInitCfm *)msg);
        }
        break;

        case GATT_MCS_CLIENT_TERMINATE_CFM:
        {
            const GattMcsClientTerminateCfm* message;
            message = (GattMcsClientTerminateCfm*) msg;
            /* Find mcp instance using connection_id_t */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                if (mcpInst->appTask != CSR_SCHED_QID_INVALID)
                {
                    mcpHandleMcsClientTerminateResp(mcpInst,
                                            (const GattMcsClientTerminateCfm *)msg);
                }
                else
                {
                    MCP_REMOVE_SERVICE_HANDLE(inst->profileHandleList, mcpInst->mcpSrvcHndl);
                    FREE_MCP_CLIENT_INST(mcpInst->mcpSrvcHndl);
                }
            }
        }
        break;

        case GATT_MCS_CLIENT_NTF_IND:
        {
            const GattMcsClientNtfInd* message;
            message = (GattMcsClientNtfInd*) msg;

            /* Find mcp instance using mcs service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                mcpHandleMcsNtfInd(mcpInst,
                                   (const GattMcsClientNtfInd *)msg);
            }
        }
        break;

        case GATT_MCS_CLIENT_NTF_CFM:
        {
            const GattMcsClientNtfCfm* message;
            message = (GattMcsClientNtfCfm*) msg;

            /* Find mcp instance using mcs service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                mcpHandleMcsNtfCfm(mcpInst,
                                   (const GattMcsClientNtfCfm *)msg);
            }
        }
        break;

        case GATT_MCS_CLIENT_GET_MEDIA_PLAYER_ATTRIBUTE_CFM:
        {
            const GattMcsClientGetMediaPlayerAttributeCfm* message;
            message = (GattMcsClientGetMediaPlayerAttributeCfm*) msg;

            /* Find mcp instance using mcs service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                mcpHandleReadCharacCfm(mcpInst, message);
            }

            if (message->value != NULL)
            {
                free(message->value);
            }
        }
        break;

        case GATT_MCS_CLIENT_SET_MEDIA_PLAYER_ATTRIBUTE_CFM:
        {
            const GattMcsClientSetMediaPlayerAttributeCfm* message;
            message = (GattMcsClientSetMediaPlayerAttributeCfm*) msg;

            /* Find mcp instance using mcs service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                mcpHandleWriteCharacCfm(mcpInst,
                                        (const GattMcsClientSetMediaPlayerAttributeCfm*)msg);
            }
        }
        break;

        case GATT_MCS_CLIENT_MEDIA_PLAYER_ATTRIBUTE_IND:
        {
            const GattMcsClientMediaPlayerAttributeInd* message;
            message = (GattMcsClientMediaPlayerAttributeInd*) msg;

            /* Find mcp instance using mcs service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                mcpHandleCharacIndCfm(mcpInst, message);
            }

            if (message->value != NULL)
            {
                free(message->value);
            }
        }
        break;

        case GATT_MCS_CLIENT_SET_MEDIA_CONTROL_POINT_CFM:
        {
            const GattMcsClientSetMediaControlPointCfm* message;
            message = (GattMcsClientSetMediaControlPointCfm*) msg;

            /* Find mcp instance using mcs service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);

            if (mcpInst)
            {
                mcpHandleMediaControlPointCfm(mcpInst,
                                              (const GattMcsClientSetMediaControlPointCfm *)msg);
            }
        }
        break;

#ifndef EXCLUDE_GATT_OTS_CLIENT_MODULE
        case GATT_MCS_CLIENT_SET_SEARCH_CONTROL_POINT_CFM:
        {
            const GattMcsClientSetSearchControlPointCfm* message;
            message = (GattMcsClientSetSearchControlPointCfm*) msg;
            
            /* Find mcp instance using mcs service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_MCS_SERVICE_HANDLE(inst->profileHandleList,
                                                       message->srvcHndl);
            if (elem)
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            
            if (mcpInst)
            {
                mcpHandleSearchControlPointCfm(mcpInst,
                                              (const GattMcsClientSetSearchControlPointCfm*)msg);
            }
            break;
        }
#endif
        default:
        {
            /* Unrecognised GATT MCS Client message */
            MCP_WARNING("Gatt MCS Client Msg not handled [0x%x]\n", *prim);
        }
        break;
    }
}

#ifndef EXCLUDE_GATT_OTS_CLIENT_MODULE
/*************************************************************/
static void mcpHandleOtsClientMsg(McpMainInst *inst, void *msg)
{
    GattOtscMessageId *prim = (GattOtscMessageId *)msg;
    ProfileHandleListElm_t *elem = NULL;
    MCP *mcpInst = NULL;

    switch (*prim)
    {
        case GATT_OTSC_INIT_CFM:
        {
            const GattOtscInitCfm *message;
            message = (GattOtscInitCfm *) msg;
            /* Find mcp instance using connection_id_t */
            elem = MCP_FIND_PROFILE_HANDLE_BY_BTCONNID(inst->profileHandleList,
                                                       message->cid);
            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }

            if (mcpInst)
            {
                uint8 optService = mcpInst->optServices;

                mcpInst->otsSrvcHndl = message->svcHandle;

                mcpInst->optServices &= ~MCP_OPTIONAL_SERVICE_OTS;
                /* Currently only one OTS instance is supported for GMCS, in future need to increment per mcs instance */
                mcpInst->optServiceCount = 1;

                /* Free the otsdata which is cached by mcpInst for reconnection case to handle */
                if (mcpInst->otsData)
                {
                    free(mcpInst->otsData);
                    mcpInst->otsData = NULL;
                }

                 /* Send the confirmation once all the optional services discovery is completed, for OTS send handle as invalid */
                if (mcpInst->optServices == MCP_OPTIONAL_SERVICE_INVALID)
                {
                     uint16 result = MCP_STATUS_SUCCESS;

                     if (message->resultCode != GATT_OTSC_RESULT_CODE_SUCCESS)
                     {
                        result = MCP_STATUS_DISCOVERY_ERR;
                        optService = MCP_OPTIONAL_SERVICE_INVALID;
                     }
                     
                     mcpSendOptServInitCfm(mcpInst, optService, result, MCP_OTS_INVALID_HANDLE);
                }
            }
        }
        break;

        case GATT_OTSC_TERMINATE_CFM:
        {
            const GattOtscTerminateCfm *message;
            message = (GattOtscTerminateCfm *)msg;

            /* Find mcp instance using connection_id_t */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);
            
            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }

            if (mcpInst)
            {
                /* Free the otsdata which is cached by mcpInst for reconnection case to handle in case of linkloss/remote disconnection */
                if (mcpInst->otsData)
                {
                    free(mcpInst->otsData);
                    mcpInst->otsData = NULL;
                }
                /* Call destroy for mcs instances post OTS termination */
                destroyServices(mcpInst, MCP_MCS_SERVICE);
            }
            else
            {
                MCP_DEBUG("MCP instance is not found\n");
            }
        }
        break;

        case GATT_OTSC_REGISTER_FOR_INDICATION_CFM:
        {
            const GattOtscRegisterForIndicationCfm *message;
            message = (GattOtscRegisterForIndicationCfm *)msg;
            
            /* Find mcp instance using connection_id_t */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);

            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }

            if (mcpInst)
            {
                mcpSendOtsRegisterForIndCfm(mcpInst, message->svcHandle, message->resultCode, CSR_BT_MCP_GET_SUPPLIER(message->resultCode));
            }
            else
            {
                MCP_DEBUG("MCP instance is not found\n");
            }
        }
        break;

        case GATT_OTSC_SELECT_OBJECT_CFM:
        {
            GattOtscSelectObjectCfm *message;
            message = (GattOtscSelectObjectCfm *)msg;
            
            /* Find mcp instance using connection_id_t */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);

            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }

            if (mcpInst)
            {
                if (mcpInst->pendingOp & MCP_PENDING_OP_START_OBJECT_DISCOVERY ||
                      mcpInst->pendingOp & MCP_PENDING_OP_STOP_OBJECT_DISCOVERY)
                {
                    MCP_INFO("GATT_OTSC_SELECT_OBJECT_CFM mcpInst->pendingOp %x message->resultCode %x\n", mcpInst->pendingOp, message->resultCode);
                    if (message->resultCode == GATT_OTSC_RESULT_CODE_SUCCESS)
                    {
                        uint16 objectMetadataType = mcpInst->otsMetadataType;
                        PerformObjectMetadataRead(mcpInst, objectMetadataType);
                    }
                    else
                    {
                        if (mcpInst->pendingOp & MCP_PENDING_OP_START_OBJECT_DISCOVERY)
                        {
                            /* Check for the OTS traversal, once all objects are traversed,
                             * MCP done with traversal, change the status to MCP_STATUS_SUCCESS */
                            if (message->resultCode == GATT_OTSC_RESULT_CODE_OUT_OF_BOUNDS)
                            {
                                 message->resultCode = MCP_STATUS_SUCCESS;
                            }
                            mcpSendStartDiscoverObjCfm(mcpInst, message->resultCode, CSR_BT_MCP_GET_SUPPLIER(message->resultCode));
                         }
                         if (mcpInst->pendingOp & MCP_PENDING_OP_STOP_OBJECT_DISCOVERY)
                         {
                             mcpSendStopDiscoverObjCfm(mcpInst, MCP_STATUS_SUCCESS, CSR_BT_MCP_GET_SUPPLIER(MCP_STATUS_SUCCESS));
                         }
                    }
                }
                else if (mcpInst->pendingOp & MCP_PENDING_OP_READ_OBJECT)
                {
                    if (message->resultCode == GATT_OTSC_RESULT_CODE_SUCCESS)
                    {
                        if (!GattOtscReadObjectReq(mcpInst->otsSrvcHndl, OBJECT_READ_OFFSET, OBJECT_READ_LENGTH, mcpInst->cid))
                        {
                            mcpSendObjContentCfm(mcpInst, NULL, MCP_STATUS_OTS_FAILED, GATT_SUPPLIER_MCP_CLIENT);
                        }
                    }
                    else
                    {
                        mcpSendObjContentCfm(mcpInst, NULL, message->resultCode, GATT_SUPPLIER_OTS_CLIENT);
                    }
                }
                else if (mcpInst->pendingOp & MCP_PENDING_OP_SELECT_OBJECT)
                {
                    mcpSendObjContentCfm(mcpInst, NULL, message->resultCode, GATT_SUPPLIER_OTS_CLIENT);
                }
                else
                {
                    MCP_DEBUG("MCP Unknown Pending OP %x\n", mcpInst->pendingOp);
                }
            }
            else
            {
                MCP_DEBUG("MCP instance is not found\n");
            }
        }
        break;

        case GATT_OTSC_READ_OBJECT_CFM :
        {
            const GattOtscReadObjectCfm *message;
            message = (GattOtscReadObjectCfm *)msg;
            
            /* Find mcp instance using service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);

            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }

            if (mcpInst)
            {
                mcpSendObjContentCfm(mcpInst, message, message->resultCode, CSR_BT_MCP_GET_SUPPLIER(message->resultCode));
            }
            else
            {
                 MCP_DEBUG("MCP instance is not found\n");
            }
        }
        break;

        case GATT_OTSC_READ_OBJECT_METADATA_CFM:
        {
            const GattOtscReadObjectMetadataCfm *message;
            message = (GattOtscReadObjectMetadataCfm *)msg;
            
            /* Find mcp instance using service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);

            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }

            if (mcpInst)
            {
                if (mcpInst->pendingOp & MCP_PENDING_OP_READ_OBJECT_METADATA)
                {
                    mcpSendObjectMetadataCfm(mcpInst, message);
                }
                else if (mcpInst->pendingOp & MCP_PENDING_OP_START_OBJECT_DISCOVERY)
                {
                    mcpSendObjectMetadataInd(mcpInst, message);

                    /* Check for current object all the metadataRead is done before making next object to be current */
                    if (mcpInst->mcpReqCount == 0)
                    {
                        if (!GattOtscSelectObjectReq(mcpInst->otsSrvcHndl, 0x00, GATT_OTSC_OBJ_LIST_OP_NEXT))
                        {
                            mcpSendStartDiscoverObjCfm(mcpInst, MCP_STATUS_OTS_FAILED, GATT_SUPPLIER_MCP_CLIENT);
                        }

                    }
                }
                else if (mcpInst->pendingOp & MCP_PENDING_OP_STOP_OBJECT_DISCOVERY)
                {
                    mcpSendObjectMetadataInd(mcpInst, message);

                    MCP_INFO("GATT_OTSC_READ_OBJECT_METADATA_CFM Pending mcpInst->mcpReqCount %x\n", mcpInst->mcpReqCount);
                    /* Check for current object all the metadataRead is done before stop disocver confirmation */
                    if (mcpInst->mcpReqCount == 0)
                    {
                         mcpSendStartDiscoverObjCfm(mcpInst, MCP_STATUS_SUCCESS, GATT_SUPPLIER_MCP_CLIENT);
                    }
                }
                else
                {
                    MCP_DEBUG("MCP Unknown Pending OP %x\n", mcpInst->pendingOp);
                }
            }
            else
            {
                 MCP_DEBUG("MCP instance is not found\n");
            }
        }
        break;

        case GATT_OTSC_ABORT_CFM:
        {
            const GattOtscAbortCfm *message;
            message = (GattOtscAbortCfm *)msg;
            
            /* Find mcp instance using service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);
            
            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }
            
            if (mcpInst)
            {
                mcpSendOtsReqAbortCfm(mcpInst, message->resultCode, CSR_BT_MCP_GET_SUPPLIER(message->resultCode));
            }
            else
            {
                 MCP_DEBUG("MCP instance is not found\n");
            }
        }
        break;

        case GATT_OTSC_OBJECT_CHANGED_IND:
        {
            GattOtscObjectChangedInd *message;
            message = (GattOtscObjectChangedInd *)msg;
            
            /* Find mcp instance using service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);
            
            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }
            
            if (mcpInst)
            {
                mcpSendOtsObjChangedInd(mcpInst, message);
            }
            else
            {
                 MCP_DEBUG("MCP instance is not found\n");
            }
        }
        break;

        case GATT_OTSC_FILTER_OBJECTS_CFM:
        {
            const GattOtscFilterObjectsCfm *message;
            message = (GattOtscFilterObjectsCfm *)msg;

            /* Find mcp instance using service handle */
            elem = MCP_FIND_PROFILE_HANDLE_BY_OTS_SERVICE_HANDLE(inst->profileHandleList,
                message->svcHandle);

            if (elem)
            {
                mcpInst = FIND_MCP_INST_BY_PROFILE_HANDLE(elem->profile_handle);
            }

            if (mcpInst)
            {
                if (message->resultCode == GATT_OTSC_RESULT_CODE_SUCCESS)
                {
                   /* Read object metadata as per spec:
                    * The Object Client shall read at least one of the Object Metadata characteristics such as 
                    * The Object Type/Size/Id/Properties/ before moving on to the next object 
                    * OTS API's are sync in nature so first check return type to decide cfm will come or not from OTS*/
                   /* The OLCP First and OLCP Next Op Codes shall be used to select the first object and to step
                    * through the objects to discover the objects available via the service. For each object selected in
                    * this way, the Object Client shall read at least one of the Object Metadata characteristics such as
                    * the Object Name before moving on to the next object */
                    if (!GattOtscSelectObjectReq(mcpInst->otsSrvcHndl, NULL, GATT_OTSC_OBJ_LIST_OP_FIRST))
                    {
                        mcpSendStartDiscoverObjCfm(mcpInst, MCP_STATUS_OTS_FAILED, GATT_SUPPLIER_MCP_CLIENT);
                    }
                    mcpInst->pendingOp |= MCP_PENDING_OP_START_OBJECT_DISCOVERY;
                }
                else
                {/* Error occured so stop and report failure to the application */
                    mcpSendStartDiscoverObjCfm(mcpInst, message->resultCode, CSR_BT_MCP_GET_SUPPLIER(message->resultCode));
                }
            }
            else
            {
                 MCP_DEBUG("MCP instance is not found\n");
            }

        }
        break;

        default :
            MCP_INFO("MCP :mcpHandleOtsClientMsg unknown msg %x\n", *prim);
           break;
    }
}
#endif /* EXCLUDE_GATT_OTS_CLIENT_MODULE */


/***************************************************************************/
static void  mcpHandleInternalMessage(McpMainInst *inst, void *msg)
{
    MCP_DEBUG("mpHandleInternalMessage Message \n");
    CSR_UNUSED(inst);
    CSR_UNUSED(msg);
}

/****************************************************************************/
void mcpMsgHandler(void **gash)
{
    CsrUint16 eventClass = 0;
    void *msg = NULL;
    McpMainInst *inst = (McpMainInst * )*gash;

    if (CsrSchedMessageGet(&eventClass, &msg))
    {
        switch (eventClass)
        {
            case GATT_SRVC_DISC_PRIM:
                handleGattSrvcDiscMsg(inst, msg);
                break;
            case MCP_PRIM:
                mcpHandleInternalMessage(inst, msg);
                break;
            case MCS_CLIENT_PRIM:
                mcpHandleGattMcsClientMsg(inst, msg);
                break;
#ifndef EXCLUDE_GATT_OTS_CLIENT_MODULE
            case OTS_CLIENT_PRIM:
                 mcpHandleOtsClientMsg(inst, msg);
#endif /* EXCLUDE_GATT_OTS_CLIENT_MODULE */
            default:
                MCP_DEBUG("Profile Msg not handled \n");
                break;
        }
        SynergyMessageFree(eventClass, msg);
    }
}
